/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>
#include <test_utilities/test_base.h>
#include <mc/common.h>
#include <mc/memory.h>
#include <vector>
#include <memory>
#include <string>

#include "../../../../drivers/internal/chip/chip_ina/ina.h"
#include "../../../../drivers/internal/bus/bus_base/bus.h"
#include "../../../../drivers/internal/hasdef.h"

using namespace dev;

namespace {
// Mock bus_base 用于测试
class mock_bus : public bus_base {
public:
    mock_bus() : bus_base(), m_read_result(HAS_OK), m_write_result(HAS_OK) {
    }

    void set_read_result(uint32_t result) {
        m_read_result = result;
    }

    void set_write_result(uint32_t result) {
        m_write_result = result;
    }

    void set_read_data(const std::vector<uint8_t>& data) {
        m_read_data = data;
    }

    uint32_t read(ACCESS_DATA_S& input) override {
        if (m_read_result == HAS_OK) {
            input.out_buffer = m_read_data;
        }
        return m_read_result;
    }

    uint32_t write(ACCESS_DATA_S& input) override {
        return m_write_result;
    }

    uint8_t get_id() override {
        return 1;
    }

    void bus_lock() override {
    }

    void bus_unlock() override {
    }

private:
    uint32_t m_read_result;
    uint32_t m_write_result;
    std::vector<uint8_t> m_read_data;
};

// Test fixture
class powermeter_test : public mc::test::TestWithEngine {
protected:
    void SetUp() override {
        TestWithEngine::SetUp();
        m_chip = std::make_shared<chip_ina>();
        m_bus = std::make_shared<mock_bus>();
    }

    void TearDown() override {
        m_chip.reset();
        m_bus.reset();
        TestWithEngine::TearDown();
    }

    mc::mutable_dict create_csr(const std::string& chip_model = "Ina220") {
        mc::mutable_dict csr;
        csr["Address"] = static_cast<uint32_t>(0x40);
        csr["OffsetWidth"] = static_cast<uint8_t>(1);
        csr["AddrWidth"] = static_cast<uint8_t>(1);
        csr["WriteTmout"] = static_cast<uint32_t>(100);
        csr["ReadTmout"] = static_cast<uint32_t>(100);
        csr["RwBlockSize"] = static_cast<uint8_t>(2);
        csr["WriteInterval"] = static_cast<uint8_t>(1);
        csr["ReadInterval"] = static_cast<uint8_t>(1);
        csr["WriteRetryTimes"] = static_cast<uint8_t>(3);
        csr["ReadRetryTimes"] = static_cast<uint8_t>(3);
        csr["ConfigurationRegister"] = static_cast<uint16_t>(0x399F);
        csr["CalibrationRegister"] = static_cast<uint16_t>(0x0A24);
        csr["ChipModel"] = chip_model;
        return csr;
    }

    std::shared_ptr<chip_ina> m_chip;
    std::shared_ptr<mock_bus> m_bus;
};

// ========== init 测试 ==========

TEST_F(powermeter_test, init_success) {
    auto csr = create_csr();
    bool result = m_chip->init(csr);
    EXPECT_TRUE(result);
}

TEST_F(powermeter_test, init_with_minimal_csr) {
    // 测试最小CSR配置
    mc::mutable_dict csr;
    csr["Address"] = static_cast<uint32_t>(0x40);
    csr["OffsetWidth"] = static_cast<uint8_t>(1);
    csr["AddrWidth"] = static_cast<uint8_t>(1);
    csr["WriteTmout"] = static_cast<uint32_t>(100);
    csr["ReadTmout"] = static_cast<uint32_t>(100);
    csr["ConfigurationRegister"] = static_cast<uint16_t>(0x399F);
    csr["CalibrationRegister"] = static_cast<uint16_t>(0x0A24);
    csr["ChipModel"] = std::string("Ina220");
    
    bool result = m_chip->init(csr);
    EXPECT_TRUE(result);
}

TEST_F(powermeter_test, init_missing_configuration_register) {
    auto csr = create_csr();
    csr.erase("ConfigurationRegister");
    
    bool result = m_chip->init(csr);
    EXPECT_FALSE(result);
}

TEST_F(powermeter_test, init_missing_calibration_register) {
    auto csr = create_csr();
    csr.erase("CalibrationRegister");
    
    bool result = m_chip->init(csr);
    EXPECT_FALSE(result);
}

TEST_F(powermeter_test, init_missing_chip_model) {
    auto csr = create_csr();
    csr.erase("ChipModel");
    
    bool result = m_chip->init(csr);
    EXPECT_FALSE(result);
}

TEST_F(powermeter_test, init_different_chip_models) {
    // 测试不同的芯片型号
    std::vector<std::string> chip_models = {"Ina220", "Ina226", "Ina238"};
    
    for (const auto& model : chip_models) {
        auto csr = create_csr(model);
        bool result = m_chip->init(csr);
        EXPECT_TRUE(result) << "Failed to init chip model: " << model;
    }
}

// ========== bit_read 测试 ==========

TEST_F(powermeter_test, bit_read_success_ina220) {
    // 初始化芯片
    auto csr = create_csr("Ina220");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus返回的数据（大端序）
    // INA芯片会进行大小端转换，所以输入是大端序，输出是小端序
    // 输入：{0x12, 0x34} (大端序，表示0x1234)
    // 输出：{0x34, 0x12} (小端序)
    std::vector<uint8_t> read_data = {0x12, 0x34};
    m_bus->set_read_data(read_data);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_read(0x01, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_OK);
    EXPECT_TRUE(error.empty());
    EXPECT_EQ(out_buffer.size(), 2);
    // 转换后应该是小端序
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[0]), 0x34);
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[1]), 0x12);
}

TEST_F(powermeter_test, bit_read_success_ina226) {
    // 初始化芯片
    auto csr = create_csr("Ina226");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus返回的数据（大端序）
    std::vector<uint8_t> read_data = {0xAB, 0xCD};
    m_bus->set_read_data(read_data);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_read(0x02, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_OK);
    EXPECT_TRUE(error.empty());
    EXPECT_EQ(out_buffer.size(), 2);
    // 转换后应该是小端序
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[0]), 0xCD);
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[1]), 0xAB);
}

TEST_F(powermeter_test, bit_read_success_ina238_single_byte) {
    // 初始化芯片
    auto csr = create_csr("Ina238");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 单字节读取（不需要大小端转换）
    std::vector<uint8_t> read_data = {0x5A};
    m_bus->set_read_data(read_data);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_read(0x03, 1, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_OK);
    EXPECT_TRUE(error.empty());
    EXPECT_EQ(out_buffer.size(), 1);
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[0]), 0x5A);
}

TEST_F(powermeter_test, bit_read_length_exceeds_maximum) {
    // 初始化芯片
    auto csr = create_csr("Ina220");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    // Ina220最大长度为2，测试长度为3
    int32_t result = m_chip->bit_read(0x01, 3, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_ERR);
    EXPECT_FALSE(error.empty());
    EXPECT_TRUE(error.find("length exceeds maximum") != std::string::npos);
}

TEST_F(powermeter_test, bit_read_no_bus) {
    // 初始化芯片但不设置bus
    auto csr = create_csr();
    m_chip->init(csr);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    // 测试没有bus的情况，应该抛出异常
    m_chip->bit_read(0x01, 2, 0, in_buffer, out_buffer, error);
    EXPECT_FALSE(error.empty());
}

TEST_F(powermeter_test, bit_read_bus_read_failure) {
    // 初始化芯片
    auto csr = create_csr();
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus返回错误
    m_bus->set_read_result(HAS_ERR);
    m_bus->set_read_data({});

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_read(0x01, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_ERR);
}

// ========== bit_write 测试 ==========

TEST_F(powermeter_test, bit_write_success) {
    // 初始化芯片
    auto csr = create_csr("Ina220");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus写入成功
    m_bus->set_write_result(HAS_OK);

    std::vector<uint8_t> in_buffer = {0x34, 0x12};  // 小端序输入
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_write(0x00, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_OK);
    EXPECT_TRUE(error.empty());
}

TEST_F(powermeter_test, bit_write_length_exceeds_maximum) {
    // 初始化芯片
    auto csr = create_csr("Ina220");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    std::vector<uint8_t> in_buffer = {0x01, 0x02, 0x03};  // 长度为3，超过最大值2
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_write(0x00, 3, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_ERR);
    EXPECT_FALSE(error.empty());
    EXPECT_TRUE(error.find("length exceeds maximum") != std::string::npos);
}

TEST_F(powermeter_test, bit_write_input_buffer_too_small) {
    // 初始化芯片
    auto csr = create_csr("Ina220");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    std::vector<uint8_t> in_buffer = {0x01};  // 长度为1，但请求长度为2
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_write(0x00, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_ERR);
    EXPECT_FALSE(error.empty());
    EXPECT_TRUE(error.find("input buffer size is too small") != std::string::npos);
}

// ========== block_read 测试 ==========

TEST_F(powermeter_test, block_read_success) {
    // 初始化芯片
    auto csr = create_csr("Ina220");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus返回的数据（大端序）
    std::vector<uint8_t> read_data = {0x11, 0x22};
    m_bus->set_read_data(read_data);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->block_read(0x01, 2, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_OK);
    EXPECT_TRUE(error.empty());
    EXPECT_EQ(out_buffer.size(), 2);
    // 转换后应该是小端序
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[0]), 0x22);
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[1]), 0x11);
}

TEST_F(powermeter_test, block_read_length_exceeds_maximum) {
    // 初始化芯片
    auto csr = create_csr("Ina220");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    // Ina220最大长度为2，测试长度为3
    int32_t result = m_chip->block_read(0x01, 3, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_ERR);
    EXPECT_FALSE(error.empty());
    EXPECT_TRUE(error.find("length exceeds maximum") != std::string::npos);
}

// ========== block_write 测试 ==========

TEST_F(powermeter_test, block_write_success) {
    // 初始化芯片
    auto csr = create_csr("Ina220");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus写入成功
    m_bus->set_write_result(HAS_OK);

    std::vector<uint8_t> in_buffer = {0x22, 0x11};  // 小端序输入
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->block_write(0x00, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_OK);
    EXPECT_TRUE(error.empty());
}

TEST_F(powermeter_test, block_write_length_exceeds_maximum) {
    // 初始化芯片
    auto csr = create_csr("Ina220");
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    std::vector<uint8_t> in_buffer = {0x01, 0x02, 0x03};  // 长度为3，超过最大值2
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->block_write(0x00, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_ERR);
    EXPECT_FALSE(error.empty());
    EXPECT_TRUE(error.find("length exceeds maximum") != std::string::npos);
}

// ========== 芯片配置测试 ==========

TEST_F(powermeter_test, chip_config_with_default_values) {
    // 测试使用默认配置值（0x7ff和0）的情况
    auto csr = create_csr();
    csr["ConfigurationRegister"] = static_cast<uint16_t>(0x7ff);
    csr["CalibrationRegister"] = static_cast<uint16_t>(0);
    
    bool result = m_chip->init(csr);
    EXPECT_TRUE(result);
    
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    
    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;
    
    // 第一次读取会触发chip_config，但由于配置值无效，应该失败
    int32_t read_result = m_chip->bit_read(0x01, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(read_result, HAS_ERR);
    EXPECT_FALSE(error.empty());
}

TEST_F(powermeter_test, chip_config_with_valid_values) {
    // 测试使用有效配置值的情况
    auto csr = create_csr();
    csr["ConfigurationRegister"] = static_cast<uint16_t>(0x399F);
    csr["CalibrationRegister"] = static_cast<uint16_t>(0x0A24);
    
    bool result = m_chip->init(csr);
    EXPECT_TRUE(result);
    
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    
    // 设置mock bus返回的数据
    std::vector<uint8_t> read_data = {0x12, 0x34};
    m_bus->set_read_data(read_data);
    m_bus->set_read_result(HAS_OK);
    m_bus->set_write_result(HAS_OK);
    
    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;
    
    // 第一次读取会触发chip_config，应该成功
    int32_t read_result = m_chip->bit_read(0x01, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(read_result, HAS_OK);
}

TEST_F(powermeter_test, chip_dump_success   ) {
    auto csr = create_csr();
    csr["ConfigurationRegister"] = static_cast<uint16_t>(0x399F);
    csr["CalibrationRegister"] = static_cast<uint16_t>(0x0A24);
    
    bool result = m_chip->init(csr);
    auto dump = m_chip->dump();
    EXPECT_FALSE(dump.empty());
}

} // namespace

